package com.sunmi.sbs.commons.Assertion;

import java.util.*;

/**
 * author: fanjia
 * date: 2020/9/24 15:03
 * file: assert.java
 */
public class Assert {
    protected Assert() {
    }

    public static HashMap<String, Boolean> assertComplete(String foo, String bar) {
        HashMap<String, Boolean> ass = new HashMap<>();

        if (assertEqual(foo, bar)) {

            ass.put("assert", true);
            ass.put("msg", null);

        } else {

            ass.put("assert", false);
            ass.put("msg", null);
        }
        return ass;

    }

    public static boolean ifAllTrue(Boolean... bools) {
        for (Boolean bool : bools) {
            if (!bool) {
                return false;
            }
        }
        return true;
    }

/*
    public static boolean assertAll(String... foos) {
        if (foos != null) {
            int typeflag = 0;
            if ((foos[0].equals("char")) || (foos[0].equals("number"))) {
                typeflag = 1;
            }

            int count = foos.length - typeflag;
            if (count < 2) {
                return false;
            } else {
                for (int i = 0; i < count - 1; i++) {
                    if (equalsRegardingNull(1, typeflag)) {
                        boolean k = assertEqual( foos[0], foos[i + typeflag], foos[i + typeflag + 1]);
                        if (!k) {
                            return false;
                        }
                    } else {
                        boolean k = assertEqual(foos[i + typeflag], foos[i + typeflag + 1]);
                        if (!k) {
                            return false;
                        }
                    }
                }
            }
            return true;
        } else {
            return false;
        }
    }
*/

    public static boolean assertAll(String type, Object foo, Object bar) {
        if (type.toLowerCase().equals("char") || type.toLowerCase().equals("number")) {
            return equalsRegardingNull(type, foo, bar);
        } else {
            return equalsRegardingNull(type, foo) && (equalsRegardingNull(type, bar));
        }
    }

    public static boolean assertAll(String type, Object foo, Object bar, Object boo) {
        if (type.equals("char") || type.equals("number")) {
            return equalsRegardingNull(type, foo, bar) && (equalsRegardingNull(type, foo, boo));
        } else {
            return equalsRegardingNull(type, foo) && (equalsRegardingNull(type, bar) && (equalsRegardingNull(type, boo)));
        }
    }

    public static boolean assertAll(String type, Object foo, Object bar, Object boo, Object far) {
        if (type.equals("char") || type.equals("number")) {
            return equalsRegardingNull(type, foo, bar) && (equalsRegardingNull(type, foo, boo)) && (equalsRegardingNull(type, foo, far));
        } else {
            return equalsRegardingNull(type, foo) && (equalsRegardingNull(type, bar) && (equalsRegardingNull(type, boo)) && (equalsRegardingNull(type, far)));
        }
    }

    public static boolean assertEqual(String type, Object foo, Object bar) {
        return equalsRegardingNull(type, foo, bar);
    }

    public static boolean assertEqual(Object foo, Object bar) {
        return equalsRegardingNull(foo, bar);
    }


    public static HashMap<String, String> assertTrueHash(Object[] objects) {
        AssertBuilder ab = new AssertBuilder();

        if (objects == null) {
            return ab.responseFalse();
        } else {
            String failMsg = null;
            String result = "true";
            for (Object object : objects) {
                HashMap hashMap = (HashMap) object;
                if ("false".equals(hashMap.get("result"))) {
                    result = "false";
//                    return ab.responseFalse((String) hashMap.get("errMsg"));
                    StringBuilder msg = ab.failMsgBuilder(hashMap);
                    failMsg = failMsg + "\n" + msg;
                }
            }
            return ab.responseBuilder(result, failMsg);
        }
    }


    public static HashMap<String, String> assertTrueHash(HashMap... hashMaps) {
        AssertBuilder ab = new AssertBuilder();
        if (hashMaps == null) {
            return ab.responseFalse();
        } else {
            for (HashMap hashMap : hashMaps) {
                if ("false".equals(hashMap.get("result"))) {
                    return ab.responseFalse((String) hashMap.get("errMsg"));
                }
            }
            return ab.responseTrue();
        }
    }


    public static HashMap<String, String> assertNumberDetail(ArrayList arrayList) {
        AssertBuilder ab = new AssertBuilder();
        StringBuilder msg = ab.failMsgBuilder(arrayList);
//        System.out.println(arrayList.toString());
//        System.out.println(arrayList.size());

        if (equalsMulti("number", arrayList)) {
            return ab.responseTrue();
        } else {
            return ab.responseFalse(fail(msg.toString()));
        }
    }

    public static HashMap<String, String> assertNumberDetail(HashMap hash) {
        AssertBuilder ab = new AssertBuilder();
        StringBuilder msg = ab.failMsgBuilder(hash);
        ArrayList arrayList = ab.hashVtoList(hash);
//        System.out.println(arrayList.toString());
//        System.out.println(arrayList.size());

        if (equalsMulti("number", arrayList)) {
            return ab.responseTrue();
        } else {
            return ab.responseFalse(fail(msg.toString()));
        }
    }

    public static HashMap<String, String> assertCharContains(ArrayList<String> arrayList) {
        AssertBuilder ab = new AssertBuilder();
        StringBuilder msg = ab.failMsgBuilder(arrayList);
//        System.out.println(arrayList.toString());
//        System.out.println(arrayList.size());
        if (containsMulti(arrayList)) {
            return ab.responseTrue();
        } else {
            return ab.responseFalse(fail(msg.toString()));
        }
    }

    public static HashMap<String, String> assertCharDetail(ArrayList arrayList) {
        AssertBuilder ab = new AssertBuilder();
        StringBuilder msg = ab.failMsgBuilder(arrayList);
//        System.out.println(arrayList.toString());
//        System.out.println(arrayList.size());
        if (equalsMulti("char", arrayList)) {
            return ab.responseTrue();
        } else {
            return ab.responseFalse(fail(msg.toString()));
        }
    }

    public static HashMap<String, String> assertCharDetail(HashMap hash) {
        AssertBuilder ab = new AssertBuilder();
        StringBuilder msg = ab.failMsgBuilder(hash);
        ArrayList arrayList = ab.hashVtoList(hash);
//        System.out.println(arrayList.toString());
//        System.out.println(arrayList.size());
        if (equalsMulti("char", arrayList)) {
            return ab.responseTrue();
        } else {
            return ab.responseFalse(fail(msg.toString()));
        }
    }

    public static boolean containsMulti(ArrayList<String> lists) {
        if (lists == null) {
            return false;
        } else {
            int len = lists.size();
            if (len < 2) {
                return false;
            } else {
                for (int i = 0; i < len - 1; i++) {
                    boolean k = containsRegardingNull(lists.get(i), lists.get(i + 1));
                    if (!k) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    public static boolean equalsMulti(String type, ArrayList lists) {
        if (lists == null) {
            return false;
        } else {
            if ((type.equals("char")) || (type.equals("number"))) {

                int len = lists.size();
                if (len < 2) {
                    return false;
                } else {
                    for (int i = 0; i < len - 1; i++) {
                        boolean k = equalsRegardingNull(type, lists.get(i), lists.get(i + 1));
                        if (!k) {
                            return false;
                        }
                    }
                }
            }
        }
        return true;


    }

    public static boolean equalsMulti(Object... objects) {
        if (objects == null) {
            return false;
        } else {
            int typeflag = 0;
            if ((objects[0].equals("char")) || (objects[0].equals("number"))) {
                typeflag = 1;
            }
            int len = objects.length - typeflag;
            if (len < 2) {
                return false;
            } else {
                for (int i = 0; i < len - 1; i++) {
                    if (equalsRegardingNull(1, typeflag)) {
                        boolean k = equalsRegardingNull((String) objects[0], objects[i + typeflag], objects[i + 1 + typeflag]);
                        if (!k) {
                            return false;
                        }
                    } else {
                        boolean k = equalsRegardingNull(objects[i + typeflag], objects[i + typeflag + 1]);
                        if (!k) {
                            return false;
                        }
                    }
                }
                return true;
            }
        }
    }


    private static boolean equalsRegardingNull(String type, Object expected, Object actual) {
        if (expected == null || actual == null) {
            return false;
        }

        if (type.toLowerCase().equals("char")) {
            return isEquals(expected, actual);
        }

        if (type.toLowerCase().equals("number")) {
            return floatIsSame(Float.parseFloat((String) expected), Float.parseFloat((String) actual));
        } else {
            return false;
        }
    }

    private static boolean containsRegardingNull(String expected, String actual) {
        if ((expected == null) || (actual == null)) {
            return false;
        }
        return isContains(expected, actual);
    }


    private static boolean equalsRegardingNull(Object expected, Object actual) {
        if ((expected == null) || (actual == null)) {
            return false;
        }

        return isEquals(expected, actual);

    }


    private static boolean isEquals(Object expected, Object actual) {
        return expected.equals(actual);
    }

    private static boolean isContains(String expected, String actual) {
        return expected.contains(actual);
    }

    private static boolean floatIsSame(float f1, float f2) {
        return Float.compare(f1, f2) == 0;
    }

    private static String fail(String message) {
        if (message == null) {
            return "fail";
        }
        return (message);
    }

}
